var common = require("./common");
var db = require("./db");
var kurento = require('kurento-client');  
const e = require("express");

class THhKms{
    constructor(aConfig){
        var me = this;
        this.config={ 
            db:{
                dbKey:"kmsManageV201001",
                dbInfo:{
                    host:"tjiot.hhdata.cn" ,
                    port:53306,
                    uid:"root",
                    pwd:"hhuc1115",
                    db:"kms202101" ,
                    sqlPath:"E:/app/kmsdev/dev/svr/sqls"
                }
            },
            kms:{
                kmsUrl : "wss://wss.hhdata.cn:8433/kurento" ,
                connectTimeout : 3*60*1000
            } 
        }
        this.objs={
            db: new db.TDBMySql(),
            client: null,
            objByCodes:{},
            objByKmsIds:{}
        }; 
        if( aConfig &&aConfig!=null){
            for ( var p in aConfig){
                if( me.config[p]){
                    me.config[p] = aConfig[p];
                }
            }
        }
        this.init();
    }
    init(){
        var me = this;
        try{
            me.objs.db.apps[me.config.db.dbKey] = me.config.db.dbInfo;
        }
        catch(er){
            console.log(er);
        }
    }
    getClient(  ){
        var me = this;
        try{
            return new Promise((success, faild)=>{ 
                if( me.objs.client && me.objs.client!=null ){
                    success(me.objs.client);
                }
                else{
                    kurento( me.config.kms.kmsUrl , function(erClient, client){ 
                        if(client && client!=null) {
                            me.objs.client = client;
                            me.scanKmsObjs(client).then(()=>{
                                success(client);
                            })
                        }
                        else{
                            success(null);
                        }
                    });
                }
            });
        }
        catch(er){
            console.log(er);
        }
    } 
    scanKmsObjs (client){
        var me = this;
        try{
            return new Promise((success, faild)=>{
                var sql ="select * from T_KmsObjs where status=1";
                var res =[];
                var freeKmsIds=['0'];
                me.objs.objByCodes ={};
                me.objs.objByKmsIds ={};
                me.objs.db.query(me.config.db.dbKey  , sql , {} , function(resObjs){ 
                    var kmsObjs = resObjs.result;
                    var scan = function(){
                        if( kmsObjs.length>0){
                            var item = kmsObjs.shift();
                            var key = [item.appId , item.code].join("_");
                            var kmsId = item.kmsId;
                            client.getMediaobjectById(kmsId , function(erFind , obj){
                                if( erFind || (!obj) || obj==null){
                                    freeKmsIds.push(kmsId);
                                }
                                else{
                                    obj.info = item;
                                    res.push(obj);
                                    me.objs.objByCodes[key] = obj;
                                    me.objs.objByKmsIds[kmsId] = obj;
                                }
                                scan();
                            });
                            
                        }
                        else{
                            if( freeKmsIds.length>1){
                                var sql = "delete from T_KmsObjs where kmsId in ('0'" ;
                                freeKmsIds.forEach(function(id){
                                    sql += ",'"+ id +"'";
                                })
                                sql += ")";
                                me.objs.db.query(me.config.db.dbKey  , sql , {} , function(resFree){
                                    success(res);    
                                });
                            }
                            else{
                                success(res);
                            }
                        }
                    }
                    scan(); 
                })

            });
        }
        catch(er){
            console.log(er);
        }
    }
    setObjInfo ( kmsObj , appId , channelId , code , desc , sessionId ){
        var me = this;
        try{
            return new Promise((success, faild)=>{
                
                var info ={
                    appId : appId , 
                    channelId : channelId ,
                    code :code ,
                    desc : desc ,
                    sessionId : sessionId ,
                    kmsId : "" ,
                    objType : "" ,
                    F_ID : 0
                };
                if( kmsObj && kmsObj!=null){
                    var arr = kmsObj.id.split(".");
                    var objType = arr[arr.length-1];
                    info.objType = objType;
                    info.kmsId = kmsObj.id;
                    var sql = "insert into T_KmsObjs(createTm , freeTm , status , objType , appId , channelId , code , kmsId , sessionId , `desc` ) values (unix_timestamp(now())   , 0 , 1 , :objType , :appId , :channelId , :code , :kmsId , :sessionId , :desc )";
                    me.objs.db.query(me.config.db.dbKey  , sql , info , function(resDB){
                        if( resDB.result && resDB.result.insertId && resDB.result.insertId >0){
                            info.F_ID = resDB.result.insertId ;
                            kmsObj.info = info;
                            var nameKey = [info.appId ,  info.code].join("_");
                            me.objs.objByCodes[nameKey] = kmsObj;
                            me.objs.objByKmsIds[info.kmsId] = kmsObj;
                            success( kmsObj );
                        }
                        else{
                            success(null);
                        }
                    });
                }
                else{
                    success( null);
                }
            });
        }
        catch(er){
            console.log(er);
        }
    }
    createKmsObj( objType, parentObj , exData, appId , channelId , sessionId ,  code , desc){
        var me = this;
        try{
            return new Promise((success , faild)=>{
                var onCreate = function(obj){
                    me.setObjInfo(obj , appId , channelId ,code , desc , sessionId).then((resSave)=>{                        
                        //obj.info = resSave;
                        success(obj); 
                    });
                }
                me.getClient().then((client)=>{
                    if( objType=="MediaPipeline" ){
                        client.create(objType , function(erPipe , pipe){
                            onCreate(pipe);
                        });
                    }
                    else if( 
                        ( 
                            objType=="WebRtcEndpoint" || 
                            objType=="RtpEndpoint" || 
                            objType=="Composite" || 
                            objType=="Dispatcher"
                        ) 
                        && parentObj && parentObj!=null){
                            parentObj.create(objType , function(erObj , Obj){
                                onCreate(Obj);
                            });
                    }
                    else if( 
                        ( 
                            objType=="PlayerEndpoint" 
                        ) 
                        && parentObj && parentObj!=null){
                            parentObj.create(objType ,{uri: exData}, function(erObj , Obj){
                                if(Obj && Obj!=null){
                                    Obj.on("EndOfStream", function(){
                                        Obj.play();
                                    });
                                    Obj.play();
                                }
                                onCreate(Obj);
                            });
                    }
                    else if( 
                        ( 
                            objType=="HubPort" 
                        ) 
                        && parentObj && parentObj!=null){
                            parentObj.createHubPort( function(erHubPort , hubPort){
                                onCreate(hubPort);
                            });
                    }
                    else{
                        success(null);
                    }
                }); 
            });

        }
        catch(er){
            console.log(er);
        }
    }
    getObjByCode( appId ,  code){
        var me = this;
        var res = null;        
        var key =[appId , code].join("_");
        if( me.objs.objByCodes[key]){
            res = me.objs.objByCodes[key];
        }
        return res;
    }
    getObjByKmsId( kmsId){
        var me = this;
        var res = null;         
        if( me.objs.objByKmsIds[kmsId]){
            res = me.objs.objByKmsIds[kmsId];
        }
        return res;
    } 
    loadObj ( objType, parentObj , exData, appId , channelId , sessionId ,  code , desc){
        var me = this;
        try{
            return new Promise((success , faild)=>{                
                var obj = me.getObjByCode( appId ,  code);
                if( obj &&  obj!=null){
                    success(obj);
                }
                else{ 
                    me.createKmsObj(objType , parentObj , exData , appId , channelId , sessionId , code , desc).then((newObj)=>{
                        success(newObj);
                    });
                }
            });

        }
        catch(er){
            console.log(er);
        }
    }
    loadObjByParentObjCode( objType, parentObjCode ,   exData, appId , channelId , sessionId ,  code , desc){
        var me = this;
        try{
            return new Promise((success , faild)=>{
                var parentObj = me.getObjByCode(appId , parentObjCode);
                me.loadObj(objType , parentObj , exData , appId , channelId , sessionId , code , desc).then((obj)=>{
                    success(obj);
                });
            }); 
        }
        catch(er){
            console.log(er);
        }
    }
    loadObjByParentObjKmsId( objType, parentObjKmsId , exData, appId , channelId , sessionId ,  code , desc){
        var me = this;
        try{
            return new Promise((success , faild)=>{
                var parentObj = me.getObjByKmsId(parentObjKmsId);
                me.loadObj(objType , parentObj , exData , appId , channelId , sessionId , code , desc).then((obj)=>{
                    success(obj);
                });

            }); 
        }
        catch(er){
            console.log(er);
        }
    }
    connectHubPort( src , target){
        var me = this;
        try{
            return new Promise((success , faild)=>{
                var arr = src.id.split("/");
                var hubId = [arr[0] , arr[1]].join("/");
                var hub = me.getObjByKmsId(hubId);
                hub.connect(src , target , function(erConn){
                    var res = {state: erConn?0:1 , error: erConn};
                    success(res);
                })

            }); 
        }
        catch(er){
            console.log(er);
        }
    }


    regist2WebSvr(webSvr){
        var me = this;
        if( webSvr && webSvr!=null){
            var respJson = function(result , response){
                try{
                    response.send(JSON.stringify(result));
                }
                catch(eer){
                    console.log(eer);
                }
            }
            webSvr.registRoute ( "common" , "hhkms" , "connectHubPort" , function( result , request , response ){                
                try{
                    var srcId = result.ps.srcId ; 
                    var targetId = result.ps.targetId;
                    var src = me.getObjByKmsId(srcId);
                    var target = me.getObjByKmsId(targetId);
                    me.connectHubPort(src , target ).then((res)=>{
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            });
            webSvr.registRoute ( "common" , "hhkms" , "setObjInfo" , function( result , request , response ){                
                try{
                    var appId = result.ps.appId ; 
                    var chId = result.ps.chId;
                    var code = result.ps.code;
                    var desc = result.ps.desc;
                    var clientId = result.ps.clientId;
                    var kmsId = result.ps.kmsId;
                    me.getClient().then(client=>{
                        client.getMediaobjectById( kmsId, function(erObj , obj){
                            if(obj && obj!=null){
                                me.setObjInfo(obj, appId , chId , code , desc , clientId).then(obj=>{
                                    result.data = (obj && obj!=null)?obj.info : null;
                                    respJson(result, response);
                                });                    
                            }
                            else{
                                result.data = (obj && obj!=null)?obj.info : null;
                                respJson(result, response);
                            }
                        });
                    }) 
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            });
            webSvr.registRoute ( "common" , "hhkms" , "getObjInfoByCode" , function( result , request , response ){                
                try{
                    var appId = result.ps.appId ; 
                    var code = result.ps.code;
                    var obj = me.getObjByCode(appId ,  code);
                    result.data = (obj && obj!=null)?obj.info : null;
                    respJson(result, response);
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            });
            webSvr.registRoute ( "common" , "hhkms" , "getObjInfoByKmsId" , function( result , request , response ){                
                try{
                    var kmsId = result.ps.kmsId ;
                    var obj = me.getObjByKmsId(kms);
                    result.data = (obj && obj!=null)?obj.info : null;
                    respJson(result, response);
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            });
            webSvr.registRoute ( "common" , "hhkms" , "loadObjByParentObjCode" , function( result , request , response ){               
                try{
                    var objType = result.ps.objType;
                    var parentCode = result.ps.parentCode;
                    var appId = result.ps.appId;
                    var channelId = result.ps.channelId;
                    var sessionId = result.ps.sessionId;
                    var code = result.ps.code;
                    var desc = result.ps.desc;
                    var exData = result.ps.exData; 
                    me.loadObjByParentObjCode(objType , parentCode , exData , appId , channelId , sessionId , code , desc ).then(obj=>{
                        result.data = (obj && obj!=null)?obj.info : null;
                        respJson(result, response);
                    }); 
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
                        
            });
            webSvr.registRoute ( "common" , "hhkms" , "loadObjByParentObjKmsId" , function( result , request , response ){               
                try{
                    var objType = result.ps.objType;
                    var parentKmsId = result.ps.parentKmsId;
                    var appId = result.ps.appId;
                    var channelId = result.ps.channelId;
                    var sessionId = result.ps.sessionId;
                    var code = result.ps.code;
                    var desc = result.ps.desc;
                    var exData = result.ps.exData; 
                    me.loadObjByParentObjKmsId(objType , parentKmsId , exData , appId , channelId , sessionId , code , desc ).then(obj=>{
                        result.data = (obj && obj!=null)?obj.info : null;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
                        
            });
            webSvr.registRoute ( "common" , "hhkms" , "getObjByCode" , function( result , request , response ){               
                try{ 
                    var appId = result.ps.appId; 
                    var code = result.ps.code; 
                    var obj = me.getObjByCode(appId , code);
                    var info = (obj && obj!=null)? obj.info : {};
                    result.data = info;
                    respJson(result, response);
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
                        
            });
        }
    }
}


module.exports={
    THhKms : THhKms
}